package org.springblade.modules.admin.controller;

import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tenant.mp.TenantEntity;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.*;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.enums.ChatGroupRobotEnum;
import org.springblade.modules.admin.enums.GroupRobotEnum;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.*;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 机器人消息推送控制器
 * 当前版本此接口前提：已通过 0000000租户 将机器人绑定至 当前租户
 * 相关管理、统计
 * @author: Sharry
 * @createTime: 2023/5/18 14:56
 * @version: Version-1.0
 */
@Slf4j
@RestController
@AllArgsConstructor
@Api(tags = "机器人消息推送控制器")
@RequestMapping("/manage/robot")
public class RobotPushController {

	private final IRobotService robotService;
	private final IChatGroupService chatGroupService;

	private final IChatGroupBuildingService chatGroupBuildingService;

	private final BuildingService buildingService;

	private final ElevatorService elevatorService;

	private final IRobotBuildingElevatorService robotBuildingElevatorService;

	private final IBuildingElevatorVisitorService bevService;

	private final IRobotBuildingElevatorService rbeService;

	private final IChatGroupService cgService;

	private final IChatGroupBuildingService cgbService;

	private final GroupRobotConfigService groupRobotConfigService;

	@GetMapping("/config/init")
	@ApiOperation("对当前已存在的所有群作初始化推送设置")
	@ApiOperationSupport(order = 9)
	public R<Boolean> configInit(){
		boolean isSuccess;
		isSuccess = groupRobotConfigService.init();
		return R.data(isSuccess);
	}

	/**
	 * 批量添加项目-电梯
	 * @return 是否成功
	 */
	@PostMapping("/add/batch")
	@ApiOperation("批量添加项目-电梯")
	@ApiOperationSupport(order = 10)
	public R<Boolean> addBatch(@RequestBody RobotBuildingElevatorListDTO relDTO){
		// 参数校验
		List<String> cgIds = relDTO.getCgIds();
		List<BuildingElevatorVO> buildingElevatorList = relDTO.getBuildingElevatorList();
		if(Func.isEmpty(cgIds) || Func.isEmpty(buildingElevatorList)){
			throw new ServiceException("添加失败！参数不完整！");
		}
		// 获取目标DTO
		List<BuildingElevatorDTO> buildingElevatorDTOList = bevService.getBuildingElevatorSelected(buildingElevatorList);
		for (String cgId : cgIds) {
			List<ChatGroup> list = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>()
				.eq(ChatGroup::getGroupId, cgId)
				.eq(ChatGroup::getTenantId,AuthUtil.getTenantId())
			);
			for (ChatGroup chatGroup : list) {
				Long id = chatGroup.getId();
				rbeService.addBatch(id,buildingElevatorDTOList);
			}
		}
		return R.data(Boolean.TRUE);
	}

	/**
	 * 批量配置群推送
	 */
	@PostMapping("/config/batch")
	@ApiOperation("批量配置推送业务")
	@ApiOperationSupport(order = 11)
	public R<Boolean> configBatch(@RequestBody GroupRobotConfigDTO groupRobotConfigDTO){
		boolean b = groupRobotConfigService.configBatch(groupRobotConfigDTO);
		return R.data(b);
	}


	/**
	 * 批量删除项目-电梯
	 * @return 是否成功
	 */
	@PostMapping("/del/batch")
	@ApiOperation("批量删除项目-电梯")
	@ApiOperationSupport(order = 20)
	public R<Boolean> delBatch(@RequestBody List<String> groupIds){
		for (String groupId : groupIds) {
			List<ChatGroup> list = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>()
				.eq(ChatGroup::getGroupId, groupId)
				.eq(ChatGroup::getTenantId, AuthUtil.getTenantId()));
			for (ChatGroup chatGroup : list) {
				Long id = chatGroup.getId();
				// 根据 这个id 获取关联的 buildingId 列表
				List<ChatGroupBuilding> chatGroupBuildingList = chatGroupBuildingService.list(new LambdaQueryWrapper<ChatGroupBuilding>()
					.eq(ChatGroupBuilding::getChatgroupId, id));
				List<Long> buildingIdList = new ArrayList<>();
				if(Func.isEmpty(chatGroupBuildingList)){
					return R.data(Boolean.TRUE);
				}
				for (ChatGroupBuilding chatGroupBuilding : chatGroupBuildingList) {
					Long buildingId = chatGroupBuilding.getBuildingId();
					buildingIdList.add(buildingId);
				}
				rbeService.delByBuildings(id,buildingIdList);
			}
		}
		return R.data(Boolean.TRUE);
	}

	/**
	 * 根据群id 删除群以及全部批量关系
	 */
	@PostMapping("/del/by/group")
	@ApiOperation("根据群id 批量删除项目电梯")
	@ApiOperationSupport(order = 21)
	public R<Boolean> delByGroup(Long chatgroupId){
		// 1. 解除 群-项目-梯关联关系
		List<RobotBuildingElevator> list
			= rbeService.list(new LambdaQueryWrapper<RobotBuildingElevator>().eq(RobotBuildingElevator::getChatgroupId, chatgroupId));
		if(Func.isNotEmpty(list)){
			List<Long> ids = new ArrayList<>();
			list.forEach(l -> ids.add(l.getId()));
			rbeService.deleteLogic(ids);
		}

		// 2. 解除  群-项目关联关系
		List<ChatGroupBuilding> list1
			= cgbService.list(new LambdaQueryWrapper<ChatGroupBuilding>().eq(ChatGroupBuilding::getChatgroupId, chatgroupId));
		if(Func.isNotEmpty(list1)){
			List<Long> ids1 = new ArrayList<>();
			list1.forEach(l1 -> ids1.add(l1.getId()));
			cgbService.deleteLogic(ids1);
		}
		// 3. 删掉群
		List<Long> ids2 = new ArrayList<>();
		ids2.add(chatgroupId);
		cgService.deleteLogic(ids2);
		return R.data(Boolean.TRUE);
	}

	/**
	 * 绑定信息列表，多条件分页查询
	 * @return 查询列表分页结果
	 */
	@TenantIgnore
	@PostMapping("/relation/list")
	@ApiOperation("绑定信息列表")
	@ApiOperationSupport(order = 30)
	public R<IPage<RobotGroupVO>> relationList(@RequestBody RobotPushDTO robotPushDTO){
		// 当前租户
		String tenantId = AuthUtil.getTenantId();
		Query query = robotPushDTO.getQuery();
		IPage<RobotGroupVO> result = chatGroupService.relationList(robotPushDTO, Condition.getPage(query),tenantId);
		return R.data(result);
	}

	/**
	 * 抬头统计信息
	 * @return 统计信息
	 */
	@GetMapping("relation/title")
	@ApiOperation("抬头统计信息")
	@ApiOperationSupport(order = 31)
	public R<GroupRobotCalculateVO> title(){
		// 当前租户id
		String tenantId = AuthUtil.getTenantId();
		GroupRobotCalculateVO groupRobotCalculateVO = new GroupRobotCalculateVO();
		// 微信群总数
		int groupCount = chatGroupService.count(new LambdaQueryWrapper<ChatGroup>().eq(ChatGroup::getTenantId, tenantId));
		// 微信群开启推送总数
		int pushAllowCount = chatGroupService.count(new LambdaQueryWrapper<ChatGroup>()
			.eq(ChatGroup::getTenantId,tenantId)
			.eq(ChatGroup::getPushAllow, ChatGroupRobotEnum.GROUP_PUSH_OPEN.getKey())
		);
		// 项目绑定总数
		List<ChatGroupBuilding> chatGroupBuildingList = chatGroupBuildingService.list(new LambdaQueryWrapper<ChatGroupBuilding>()
			.eq(ChatGroupBuilding::getTenantId, tenantId)
			.eq(BaseEntity::getIsDeleted, 0)
		);
		// 根据building_id去重，求去重后的总数
		int buildingNum = (int)chatGroupBuildingList.stream().filter(distinctByKey(ChatGroupBuilding::getBuildingId)).count();

		// 租户项目数
		int tenantBuildings = buildingService.count(new LambdaQueryWrapper<Building>()
			.eq(TenantEntity::getTenantId, tenantId)
		);

		// 租户电梯总数
		int tenantElevators = elevatorService.count(new LambdaQueryWrapper<Elevator>().eq(TenantEntity::getTenantId, tenantId));
		// 电梯绑定总数
		int elevatorNum;

		List<RobotBuildingElevator> rbeList = robotBuildingElevatorService.list(new LambdaQueryWrapper<RobotBuildingElevator>()
			.eq(RobotBuildingElevator::getTenantId, tenantId));

		elevatorNum = (int)rbeList.stream().filter(distinctByKey(RobotBuildingElevator::getElevatorId)).count();

		// 赋值
		groupRobotCalculateVO.setGroupCount(groupCount);
		groupRobotCalculateVO.setPushAllowCount(pushAllowCount);
		groupRobotCalculateVO.setBuildingCalculate(buildingNum+"/"+tenantBuildings);
		groupRobotCalculateVO.setElevatorCalculate(elevatorNum+"/"+tenantElevators);
		groupRobotCalculateVO.setElevatorNum(elevatorNum);
		groupRobotCalculateVO.setBuildingNum(buildingNum);
		groupRobotCalculateVO.setTenantBuildings(tenantBuildings);
		groupRobotCalculateVO.setTenantElevators(tenantElevators);

		return R.data(groupRobotCalculateVO);
	}

	/**
	 * 获取当前租户下所有机器人QRCode
	 * @return 返回当前租户所有机器人QRCode列表
	 */
	@GetMapping("relation/qrCode")
	@ApiOperation("获取当前租户下所有机器人QRCode")
	@ApiOperationSupport(order = 32)
	public R<List<String>> qrCodeList(){
		String tenantId = AuthUtil.getTenantId();
		List<Robot> list = robotService.list(new LambdaQueryWrapper<Robot>().eq(Robot::getTenantId, tenantId));
		List<String> urls = new ArrayList<>();

		list.forEach(l -> urls.add(l.getRobotQrcode()));

		return R.data(urls);
	}

	/**
	 * 搜索框： 获取当前租户下所有项目列表
	 * @return 项目列表
	 */
	@GetMapping("/relation/buildingSearch")
	@ApiOperation("获取当前租户下所有项目列表")
	@ApiOperationSupport(order = 33)
	public R<List<RobotBuildingVO>> getBuildingSearch(){
		String tenantId = AuthUtil.getTenantId();
		List<RobotBuildingVO> voList = new ArrayList<>();
		List<Building> list = buildingService.list(new LambdaQueryWrapper<Building>().eq(TenantEntity::getTenantId, tenantId));
		for (Building building : list) {
			RobotBuildingVO r = new RobotBuildingVO();
			r.setBuildingId(building.getId());
			r.setBuildingName(building.getName());
			voList.add(r);
		}
		return R.data(voList);
	}

	/**
	 * 搜索框 ： 获取当前租户-项目下所有电梯列表（id 与 详细位置）
	 * @return 电梯列表VO
	 */
	@PostMapping("/relation/elevatorSearch")
	@ApiOperation("根据项目id列表获取项目电梯")
	@ApiOperationSupport(order = 34)
	public R<List<RobotElevatorSearchVO>> getElevatorSearch(@RequestBody RobotPushDTO robotPushDTO){
		List<Long> buildingIds = robotPushDTO.getBuildingIds();
		List<RobotElevatorSearchVO> result = elevatorService.getElevatorSearch(buildingIds);
		return R.data(result);
	}

	/**
	 * hover 结构拆分，hover的时候再请求
	 * @return Hover 结构
	 */
	@PostMapping("/relation/list/hover")
	@ApiOperation("hover结构拆分")
	@ApiOperationSupport(order = 35)
	public R<List<RobotBuildingElevatorPushVO>> getHoverList(@RequestBody RobotHoverDTO robotHoverDTO){
		if(Func.isNull(robotHoverDTO)){
			throw new ServiceException("业务异常，参数必须传入");
		}
		String groupId = robotHoverDTO.getListId();
		List<RobotBuildingElevatorPushVO> beVoList = chatGroupService.getBeVoList(groupId,robotHoverDTO);
		return R.data(beVoList);
	}

	/**
	 * 当前群 推送设置 hover 结构
	 */
	@GetMapping("/relation/list/config")
	@ApiOperation("推送配置信息hover结构")
	@ApiOperationSupport(order = 36)
	public R<List<GroupRobotConfig>> getConfigHover(Long groupId){
		if(Func.isNull(groupId)){
			throw new ServiceException("业务异常，参数必须传入");
		}
		List<GroupRobotConfig> resultList = groupRobotConfigService.list(
			new LambdaQueryWrapper<GroupRobotConfig>()
				.eq(GroupRobotConfig::getChatgroupId,groupId)
				.eq(BaseEntity::getIsDeleted,0)
		);
		return R.data(resultList);
	}

	/**
	 * 批量开启消息推送
	 * @return 是否成功
	 */
	@PostMapping("/open/batch")
	@ApiOperation("批量开启消息推送")
	@ApiOperationSupport(order = 40)
	public R<Boolean> openBatch(@RequestBody GroupOpenDTO groupOpenDTO){
		String tenantId = AuthUtil.getTenantId();
		List<String> groupIds = groupOpenDTO.getGroupIds();
		boolean isSuccess = true;
		for (String groupId : groupIds) {
			List<ChatGroup> list = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>()
				.eq(ChatGroup::getGroupId, groupId)
				.eq(ChatGroup::getTenantId, tenantId)
			);
			for (ChatGroup chatGroup : list) {
				chatGroup.setPushAllow(ChatGroupRobotEnum.GROUP_PUSH_OPEN.getKey());
				isSuccess = isSuccess && chatGroupService.updateById(chatGroup);
			}
		}
		return R.data(isSuccess);
	}

	/**
	 * 批量关闭消息推送
	 * @return 是否成功
	 */
	@PostMapping("/close/batch")
	@ApiOperation("批量关闭消息推送")
	@ApiOperationSupport(order = 41)
	public R<Boolean> closeBatch(@RequestBody GroupOpenDTO groupOpenDTO){
		String tenantId = AuthUtil.getTenantId();
		List<String> groupIds = groupOpenDTO.getGroupIds();
		boolean isSuccess = true;
		for (String groupId : groupIds) {
			List<ChatGroup> list = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>()
				.eq(ChatGroup::getGroupId, groupId)
				.eq(ChatGroup::getTenantId, tenantId)
			);
			for (ChatGroup chatGroup : list) {
				chatGroup.setPushAllow(ChatGroupRobotEnum.GROUP_PUSH_CLOSE.getKey());
				isSuccess = isSuccess && chatGroupService.updateById(chatGroup);
			}
		}
		return R.data(isSuccess);
	}

	/**
	 * 去重方法
	 * @param keyExtractor 去重依据
	 * @param <T> 占位符
	 */
	public <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
		Map<Object,Boolean> seen = new ConcurrentHashMap<>();
		return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
	}

}
